#!/usr/bin/ruby
# -*- ruby -*-
#
# http://programmingpraxis.com/2012/10/26/pythagorean-triples/

limit = (ARGV.first || 1_000_000).to_i

class TupleSequence
    include Enumerable

    attr_reader :start, :dimension, :limit
    def initialize(start = 0, dimension = 3, limit = 10)
        @start = start
        @dimension = dimension
        @limit = limit
    end

    def each(start = @start, level = 0, agg = [], &blk)
        if level == @dimension
            yield agg
        else
            (start .. (@limit - 1)).each do |i|
                each(i, level + 1, Array.new(agg) << i, &blk)
            end
        end
    end
end

conditions = [
    lambda { |t| (t[0] * t[0] + t[1] * t[1]) == (t[2] * t[2])},
    lambda { |t| (t[0] + t[1] + t[2]) <= limit }
]

coll = TupleSequence.new(1, 3, limit).select do |t|
pp t
    conditions.inject(true) { |r, cond| r &&= cond.call(t) }
end

coll.each do |pt|
    puts "[#{pt[0]}, #{pt[1]}, #{pt[2]}]"
end
